﻿using Red.Controls.ViewModels;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Red.Core.Containers;

namespace Red.Toolkit.HoudiniDispatch
{
    /// <summary>
    /// Root Node for Job Properties
    /// </summary>
    public class JobRoot : DataItem
    {
        #region C-tor
        public JobRoot()
            : base( null )
        {
            InitJobDefinitions();
        }
        #endregion C-tor

        #region Data
        public override string Type { get { return ""; } }
        public override string Value { get { return ""; } set { } }
        //public override bool IsLeaf { get { return false; } }
        public string SelectedJobType { get; set; }
        public override DataItemKind Kind { get { return DataItemKind.Compound; } }
        #endregion Data

        #region Enumerator Implementation
        protected override Task EnumerateChildrenAsync( IRangedCollection<DataItem> children )
        {
            foreach ( JobDefinition jd in HoudiniJobManager.JobDefinitions )
            {
                if ( SelectedJobType == jd.name )
                {
                    foreach ( JobParameter jp in jd.Params )
                    {
                        DataItem ji;
                        switch ( jp.Type )
                        {
                            case "i":
                                if ( ("" != jp.min) && ("" != jp.max) )
                                {
                                    ji = new JobItem_RangedInt( this, jp.Name + "|" + jp.Type, jp.DefValue, jp.min, jp.max );
                                    children.Add( ji );
                                }
                                else
                                {
                                    ji = new JobItem_Int( this, jp.Name + "|" + jp.Type, jp.DefValue );
                                    children.Add( ji );
                                }
                                break;
                            case "v":
                                string[] vs = jp.DefValue.Split(';');
                                ji = new JobItem_VectorFloat( this, jp.Name + "|" + jp.Type, vs[0], vs[1], vs[2] );
                                children.Add( ji );
                                break;
                            default:
                                ji = new JobItem_String( this, jp.Name + "|" + jp.Type, jp.DefValue );
                                children.Add( ji );
                                break;
                        }
                        if( "Vector" != jp.Type)
                            ji.Value = jp.DefValue;
                    }
                    break;
                }
            }

            return Task.CompletedTask;
        }
        #endregion Enumerator Implementation

        #region Private Methods
        private void InitJobDefinitions()
        {
            HoudiniJobManager.LoadJobDefinitions( this );
        }
        #endregion Private Methods
    }

    /// <summary>
    /// Basic String item limited to 256 characters
    /// </summary>
    public class JobItem_String : DataItem
    {
        #region Data
        private string _val;

        public override string Value
        {
            get
            {
                return _val;
            }

            set
            {
                _val = value;
                OnPropertyChanged();
            }
        }

        public override string Type { get { return "String"; } }

        public override DataItemKind Kind { get { return DataItemKind.Simple; } }

        #endregion Data

        #region C-tor
        public JobItem_String( DataItem parent, string name, string val )
            : base( parent )
        {
            Title = name;
            _val = val;
        }
        #endregion C-tor
    }

    /// <summary>
    /// Int32 item (No Range Defined)
    /// </summary>
    public class JobItem_Int : DataItem
    {
        #region Data
        private int _val;

        public override string Value
        {
            get
            {
                return _val.ToString();
            }

            set
            {
                if ( !value.Contains( "." ) )
                    _val = int.Parse( value );
                else
                {
                    _val = Convert.ToInt32( float.Parse( value ) );
                }
                OnPropertyChanged();
            }
        }

        public override string Type { get { return "Int"; } }

        public override DataItemKind Kind { get { return DataItemKind.Simple; } }
        #endregion Data

        #region C-tor
        public JobItem_Int( DataItem parent, string name, int val )
            : base( parent )
        {
            Title = name;
            _val = val;
        }

        public JobItem_Int( DataItem parent, string name, string val )
            : base( parent )
        {
            Title = name;
            int.TryParse(val, out _val);
        }
        #endregion C-tor
    }

    /// <summary>
    /// Float item (No Range Defined)
    /// </summary>
    public class JobItem_Float : DataItem
    {
        #region Data 
        private float _val;

        public override string Value
        {
            get
            {
                return _val.ToString();
            }

            set
            {
                _val = int.Parse( value );
                OnPropertyChanged();
            }
        }

        public override string Type { get { return "Int"; } }

        public override DataItemKind Kind { get { return DataItemKind.Simple; } }
        #endregion Data

        #region C-tor
        public JobItem_Float( DataItem parent, string name, float val )
            : base( parent )
        {
            Title = name;
            _val = val;
        }

        public JobItem_Float( DataItem parent, string name, string val )
            : base( parent )
        {
            Title = name;
            float.TryParse( val, out _val );
        }
        #endregion C-tor
    }

    /// <summary>
    /// Int32 item (Range Defined)
    /// </summary>
    public class JobItem_RangedInt : JobItem_Int
    {
        #region Data
        private int _min;
        private int _max;

        public int Min { get { return _min; } }
        public int Max { get { return _max; } }

        public JobItem_RangedInt( DataItem parent, string name, int val, int min, int max )
            : base( parent, name, val )
        {
            _min = min;
            _max = max;
        }

        public JobItem_RangedInt( DataItem parent, string name, string val, string min, string max )
            : base( parent, name, val )
        {
            int.TryParse( min, out _min );
            int.TryParse( max, out _max );
        }

        public override string Type { get { return "Int:Ranged"; } }
        #endregion Data

        #region Enumerator Implementation
        protected override Task EnumerateChildrenAsync( IRangedCollection<DataItem> children )
        {
            children.Clear();
            children.Add( new JobItem_Int( this, "_min", _min ) );
            children.Add( new JobItem_Int( this, "_max", _max ) );
            return Task.CompletedTask;
        }
        #endregion Enumerator Implementation
    }

    /// <summary>
    /// Float item (Range Defined)
    /// </summary>
    public class JobItem_RangedFloat : JobItem_Float
    {
        #region Data
        private float _min;
        private float _max;

        public float Min { get { return _min; } }
        public float Max { get { return _max; } }

        public override string Type { get { return "Int:Ranged"; } }

        #endregion Data

        #region C-tor
        public JobItem_RangedFloat( DataItem parent, string name, float val, float min, float max )
            : base( parent, name, val )
        {
            _min = min;
            _max = max;
        }

        public JobItem_RangedFloat( DataItem parent, string name, string val, string min, string max )
            : base( parent, name, val )
        {
            float.TryParse( min, out _min );
            float.TryParse( max, out _max );
        }
        #endregion C-tor

        #region Enumerator Implementation
        protected override Task EnumerateChildrenAsync( IRangedCollection<DataItem> children )
        {
            children.Clear();
            children.Add( new JobItem_Float( this, "_min", _min ) );
            children.Add( new JobItem_Float( this, "_max", _max ) );
            return Task.CompletedTask;
        }
        #endregion Enumerator Implementation
    }

    /// <summary>
    /// Three-element Int32 Vector (X,Y,Z) item
    /// </summary>
    public class JobItem_VectorInt : DataItem
    {
        #region Data
        private readonly int _x, _y, _z;

        public override string Value { get { return ""; } set { } }

        public override string Type { get { return "Vector"; } }

        public override DataItemKind Kind { get { return DataItemKind.Compound; } }
        
        #endregion Data

        #region C-tor
        public JobItem_VectorInt( DataItem parent, string name, int x, int y, int z )
            : base( parent )
        {
            Title = name;
            _x = x;
            _y = y;
            _z = z;
        }
        public JobItem_VectorInt( DataItem parent, string name, string x, string y, string z )
            : base( parent )
        {
            Title = name;
            //_x = x;
            int.TryParse( x, out _x );
            //_y = y;
            int.TryParse( y, out _y );
            //_z = z;
            int.TryParse( z, out _z );
        }
        #endregion C-tor

        #region Enumerator Implementation
        protected override Task EnumerateChildrenAsync( IRangedCollection<DataItem> children )
        {
            children.Clear();
            children.Add( new JobItem_Float( this, "X", _x ) );
            children.Add( new JobItem_Float( this, "Y", _y ) );
            children.Add( new JobItem_Float( this, "Z", _z ) );
            return Task.CompletedTask;
        }
        #endregion Enumerator Implementation
    }

    /// <summary>
    /// Three-element Float Vector (X,Y,Z) item
    /// </summary>
    public class JobItem_VectorFloat : DataItem
    {
        #region Data
        private readonly float _x, _y, _z;

        public override string Value { get { return ""; } set { } }

        public override string Type { get { return "Vector"; } }

        public override DataItemKind Kind { get { return DataItemKind.Compound; } }

        #endregion Data

        #region C-tor
        public JobItem_VectorFloat( DataItem parent, string name, float x, float y, float z )
            : base( parent )
        {
            Title = name;
            _x = x;
            _y = y;
            _z = z;
        }

        public JobItem_VectorFloat( DataItem parent, string name, string x, string y, string z )
            : base( parent )
        {
            Title = name;
            //_x = x;
            float.TryParse( x, out _x );
            //_y = y;
            float.TryParse( y, out _y );
            //_z = z;
            float.TryParse( z, out _z );
        }
        #endregion C-tor

        #region Enumerator Implementation
        protected override Task EnumerateChildrenAsync( IRangedCollection<DataItem> children )
        {
            children.Clear();
            children.Add( new JobItem_Float( this, "X", _x ) );
            children.Add( new JobItem_Float( this, "Y", _y ) );
            children.Add( new JobItem_Float( this, "Z", _z ) );
            return Task.CompletedTask;
        }
        #endregion Enumerator Implementation
    }
}
